package com.szwistar.common.datastruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedHashMap;
import java.util.Map;

public class JsonObject extends LinkedHashMap<String, Object> {
	private static final long serialVersionUID = 4953311659969546138L;
	protected static final Logger LOG = LoggerFactory.getLogger(JsonObject.class);

	public JsonObject() {
		super();
	}

	public JsonObject(Object ...args) {
		super();
		if(args == null || (args.length%2 != 0)) { throw new RuntimeException("错误的参数"); }
		for(int i=0; i<args.length/2; i++) {
			// key 必须是字符串
			if(!(args[2*i] instanceof String)) { throw new RuntimeException("错误的参数"); }
			// 取得 key
			String key = (String)args[2*i];
			// 取得 value: 跳过空值
			Object val = args[2*i+1]; if(val == null) { continue; }
			// 放入
			put(key, val);
		}
	}

	public JsonObject(Map<String, Object> val) {
		super(val);
	}

	public static JsonObject parse(String json) throws Exception {
		return JsonMapper.fromJson(json);
	}

	public String toJson() throws Exception {
		return JsonMapper.toJson(this);
	}

	@SuppressWarnings("unchecked")
	public <T> T getToType(Class<T> clazz, String key, T defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(clazz.isAssignableFrom(val.getClass())) {
				return (T) val;
			} else if(val instanceof String) {
				return JsonMapper.fromJson((String)val, clazz);
			} else {
				return null;
			}
		} catch (Exception e) {
			LOG.error("{}", e.toString());
		}

		return defaultValue;
	}

	@SuppressWarnings("unchecked")
	public JsonObject getJsonObject(String key, JsonObject defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return JsonObject.parse((String)val);
			} else if(val instanceof Map) {
				return new JsonObject((Map<String, Object>)val);
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}

	public <T> T getRecursively(Class<T> clazz, T defaultValue, String ...path) {
		if(Utils.isEmpty(path)) { return defaultValue; }

		int i;
		JsonObject val = getJsonObject(path[0], null);
		for(i=1; i<path.length-1; i++) {
			if(val == null) { return defaultValue; }
			val = val.getJsonObject(path[i], null);
		}
		return (val == null) ? defaultValue : val.getToType(clazz, path[i], defaultValue);
	}

	public String getStr(String key, String defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		if(val instanceof String) {
			return (String)val;
		} else {
			return val.toString();
		}
	}

	public Short getShort(String key, Short defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return Short.parseShort((String)val);
			} else if(Integer.class.isAssignableFrom(val.getClass())) {
				return (Short) val;
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}

	public Integer getInt(String key, Integer defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return Integer.parseInt((String)val);
			} else if(Integer.class.isAssignableFrom(val.getClass())) {
				return (Integer) val;
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}

	public Long getLong(String key, Long defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return Long.parseLong((String)val);
			} else if(Long.class.isAssignableFrom(val.getClass())) {
				return (Long) val;
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}

	public Float getFloat(String key, Float defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return Float.parseFloat((String)val);
			} else if(Float.class.isAssignableFrom(val.getClass())) {
				return (Float) val;
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}

	public Boolean getBoolean(String key, Boolean defaultValue) {
		Object val = get(key);
		if(val == null) { return defaultValue; }

		try {
			if(val instanceof String) {
				return Boolean.parseBoolean((String)val);
			} else if(Boolean.class.isAssignableFrom(val.getClass())) {
				return (Boolean) val;
			}
		} catch (Exception e) {
		}

		return defaultValue;
	}
}
